home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / BNU22SR1.ZIP / src / binutils.2 / bfd / coff-rs6.c < prev    next >
C/C++ Source or Header  |  1993-05-30  |  9KB  |  352 lines

  1. /* BFD back-end for IBM RS/6000 "XCOFF" files.
  2.    Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  3.    Written by Metin G. Ozisik, Mimi Ph√⌠ng-Thσo V⌡, and John Gilmore.
  4.    Archive support from Damon A. Permezel.
  5.    Contributed by IBM Corporation and Cygnus Support.
  6.  
  7. This file is part of BFD, the Binary File Descriptor library.
  8.  
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13.  
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  22.  
  23. /* This port currently only handles reading object files, except when
  24.    compiled on an RS/6000 host.  -- no archive support, no core files.
  25.    In all cases, it does not support writing.
  26.  
  27.    FIXMEmgo comments are left from Metin Ozisik's original port.  */
  28.  
  29. /* Internalcoff.h and coffcode.h modify themselves based on this flag.  */
  30. #define RS6000COFF_C 1
  31.  
  32. #include "bfd.h"
  33. #include "sysdep.h"
  34. #include "libbfd.h"
  35. #include "obstack.h"
  36. #include "coff/internal.h"
  37. #include "coff/rs6000.h"
  38. #include "libcoff.h"
  39.  
  40. /* The main body of code is in coffcode.h.  */
  41.  
  42. /* Can't read rs6000 relocs */
  43. #define RTYPE2HOWTO(a,b)
  44. #include "coffcode.h"
  45.  
  46. #define    coff_archive_p        bfd_generic_archive_p
  47. #define    coff_mkarchive        _bfd_generic_mkarchive
  48.  
  49. #ifdef ARCHIVES_PLEASE
  50.  
  51. /* ------------------------------------------------------------------------ */
  52. /*    Support for archive file stuff..                    */
  53. /*    Stolen from Damon A. Permezel's `bfd' portation.            */
  54. /* ------------------------------------------------------------------------ */
  55.  
  56. #undef    coff_openr_next_archived_file
  57. #define coff_openr_next_archived_file    rs6000coff_openr_next_archived_file
  58.  
  59. #undef    coff_write_armap
  60. #define coff_write_armap        rs6000coff_write_armap
  61.  
  62. #undef    coff_stat_arch_elt
  63. #define    coff_stat_arch_elt        rs6000coff_stat_arch_elt
  64.  
  65. #undef    coff_snarf_ar_hdr
  66. #define    coff_snarf_ar_hdr        rs6000coff_snarf_ar_hdr
  67.  
  68. #undef    coff_mkarchive
  69. #define    coff_mkarchive            rs6000coff_mkarchive
  70.  
  71. #undef    coff_archive_p
  72. #define    coff_archive_p            rs6000coff_archive_p
  73.  
  74. #include "/usr/include/ar.h"        /* <ar.h> doesn't do it.    */
  75.  
  76.  
  77. #define arch_hdr(bfd)         \
  78.     ((struct ar_hdr *)    \
  79.      (((struct areltdata *)((bfd)->arelt_data))->arch_header))
  80.  
  81.  
  82. static boolean
  83. rs6000coff_mkarchive (abfd)
  84.      bfd *abfd;
  85. {
  86.     bfd_error = invalid_operation;    /* write not supported    */
  87. }
  88.  
  89.  
  90. /* This functions reads an arch header and returns an areltdata pointer, or
  91.    NULL on error.
  92.  
  93.    Presumes the file pointer is already in the right place (ie pointing
  94.    to the ar_hdr in the file).   Moves the file pointer; on success it
  95.    should be pointing to the front of the file contents; on failure it
  96.    could have been moved arbitrarily.
  97. */
  98.  
  99. struct areltdata *
  100. rs6000coff_snarf_ar_hdr (abfd)
  101.      bfd *abfd;
  102. {
  103.     extern int errno;
  104.  
  105.     struct {
  106.         struct ar_hdr hdr;
  107.         char namebuf[256];
  108.     } h;
  109.     int size;
  110.     struct areltdata *ared;
  111.     unsigned int namelen = 0;
  112.     char *allocptr;
  113.  
  114.     size = sizeof (h.hdr);
  115.     if (bfd_read(&h.hdr, 1, size, abfd) != size) {
  116.         bfd_error = no_more_archived_files;
  117.         return NULL;
  118.     }
  119.     size  = atoi(h.hdr.ar_namlen);    /* ar_name[] length    */
  120.     size += size & 1;
  121.  
  122.     if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) {
  123.         bfd_error = no_more_archived_files;
  124.         return NULL;
  125.     }
  126.  
  127.     if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
  128.         bfd_error = malformed_archive;
  129.         return NULL;
  130.     }
  131.  
  132.     h.hdr._ar_name.ar_name[size] = 0;    /* terminate filename    */
  133.  
  134.     /*
  135.      * if the filename is NULL, we're (probably) at the end.
  136.      */
  137.     if (size == 0) {
  138.         bfd_error = no_more_archived_files;
  139.         return NULL;
  140.     }
  141.  
  142.     size += sizeof (h.hdr);
  143.     allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
  144.  
  145.     if (allocptr == NULL) {
  146.         bfd_error = no_memory;
  147.         return NULL;
  148.     }
  149.  
  150.     ared = (struct areltdata *) allocptr;
  151.  
  152.     ared->arch_header = (void *) (allocptr + sizeof (struct areltdata));
  153.     memcpy ((char *) ared->arch_header, &h.hdr, size);
  154.     ared->parsed_size = atoi(h.hdr.ar_size);
  155.     ared->filename    = ((AR_HDR*) ared->arch_header)->_ar_name.ar_name;
  156.  
  157.     return ared;
  158. }
  159.  
  160. /* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr.
  161.    Why wasn't this part of the transfer vector?  */
  162.  
  163. bfd *
  164. rs6000coff_get_elt_at_filepos (archive, filepos)
  165.      bfd *archive;
  166.      file_ptr filepos;
  167. {
  168.   struct areltdata *new_areldata;
  169.   bfd *n_nfd;
  170.  
  171.   n_nfd = look_for_bfd_in_cache (archive, filepos);
  172.   if (n_nfd) return n_nfd;
  173.  
  174.   if (0 != bfd_seek (archive, filepos, SEEK_SET)) {
  175.     bfd_error = system_call_error;
  176.     return NULL;
  177.   }
  178.  
  179.   if ((new_areldata = rs6000coff_snarf_ar_hdr (archive)) == NULL) return NULL;
  180.   
  181.   n_nfd = _bfd_create_empty_archive_element_shell (archive);
  182.   if (n_nfd == NULL) {
  183.     bfd_release (archive, (PTR)new_areldata);
  184.     return NULL;
  185.   }
  186.   n_nfd->origin = bfd_tell (archive);
  187.   n_nfd->arelt_data = (PTR) new_areldata;
  188.   n_nfd->filename = new_areldata->filename;
  189.  
  190.   if (add_bfd_to_cache (archive, filepos, n_nfd))
  191.     return n_nfd;
  192.  
  193.   /* huh? */
  194.   bfd_release (archive, (PTR)n_nfd);
  195.   bfd_release (archive, (PTR)new_areldata);
  196.   return NULL;
  197. }
  198.  
  199. /*
  200.  * xcoff_openr_next_archived_file -    xcoff has nxt/prv seek addrs.
  201.  */
  202. static bfd *
  203. rs6000coff_openr_next_archived_file(archive, last_file)
  204.   bfd *archive, *last_file; 
  205. {
  206.     file_ptr filestart;
  207.  
  208.     if (!last_file)
  209.         filestart = bfd_ardata(archive)->first_file_filepos;
  210.     else
  211.         filestart = atol(arch_hdr(last_file)->ar_nxtmem);
  212.  
  213.     return rs6000coff_get_elt_at_filepos (archive, filestart);
  214. }
  215.  
  216.  
  217. static bfd_target *
  218. rs6000coff_archive_p (abfd)
  219.      bfd *abfd;
  220. {
  221.     struct fl_hdr hdr;
  222.     register struct artdata *art;
  223.  
  224.     if (bfd_read (&hdr, sizeof (hdr), 1, abfd) != sizeof (hdr)) {
  225.         bfd_error = wrong_format;
  226.         return 0;
  227.     }
  228.  
  229.     if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
  230.         bfd_error = wrong_format;
  231.         return 0;
  232.     }
  233.  
  234.     /*
  235.      * bfd_ardata() accesses the bfd->tdata field.
  236.      */
  237.     abfd->tdata.aout_ar_data =
  238.       (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr));
  239.     if ((art = bfd_ardata (abfd)) == NULL) {
  240.         bfd_error = no_memory;
  241.         return 0;
  242.     }
  243.  
  244.     art->first_file_filepos = atoi(hdr.fl_fstmoff);
  245.     *(struct fl_hdr *) (1 + art) = hdr;
  246.  
  247.     /* Someday...
  248.      * slurp in the member table, which I think is the armap equivalent.
  249.     xcoff_slurp_armap(abfd);
  250.      */
  251.   
  252.     return abfd->xvec;
  253. }
  254.  
  255.  
  256. static int
  257. rs6000coff_stat_arch_elt(abfd, buf)
  258.   bfd *abfd;
  259.   struct stat *buf;
  260. {
  261.     struct ar_hdr *hdr;
  262.     char *aloser;
  263.   
  264.     if (abfd->arelt_data == NULL) {
  265.         bfd_error = invalid_operation;
  266.         return -1;
  267.     }
  268.     
  269.     hdr = arch_hdr (abfd);
  270.  
  271. #define foo(arelt, stelt, size)  \
  272.     buf->stelt = strtol (hdr->arelt, &aloser, size); \
  273.         if (aloser == hdr->arelt) return -1;
  274.   
  275.     foo (ar_date, st_mtime, 10);
  276.     foo (ar_uid, st_uid, 10);
  277.     foo (ar_gid, st_gid, 10);
  278.     foo (ar_mode, st_mode, 8);
  279.     foo (ar_size, st_size, 10);
  280. #undef foo
  281.  
  282.     return 0;
  283. }
  284.  
  285. static boolean
  286. rs6000coff_write_armap (arch, elength, map, orl_count, stridx)
  287.   bfd *arch;
  288.   unsigned int elength;
  289.   struct orl *map; 
  290. {
  291.     bfd_error = invalid_operation;
  292.     return false;
  293. }
  294. #endif    /* ARCHIVES_PLEASE */
  295.  
  296.  
  297. #ifdef COREFILES_PLEASE
  298. extern bfd_target * rs6000coff_core_p ();
  299. extern boolean rs6000coff_get_section_contents ();
  300. extern boolean rs6000coff_core_file_matches_executable_p ();
  301.  
  302. #undef    coff_core_file_matches_executable_p
  303. #define coff_core_file_matches_executable_p  \
  304.                      rs6000coff_core_file_matches_executable_p
  305.  
  306. #undef    coff_get_section_contents
  307. #define    coff_get_section_contents    rs6000coff_get_section_contents
  308. #endif
  309.  
  310. /* The transfer vector that leads the outside world to all of the above. */
  311.  
  312. bfd_target rs6000coff_vec =
  313. {
  314.   "aixcoff-rs6000",        /* name */
  315.   bfd_target_coff_flavour,    
  316.   true,                /* data byte order is big */
  317.   true,                /* header byte order is big */
  318.  
  319.   (HAS_RELOC | EXEC_P |        /* object flags */
  320.    HAS_LINENO | HAS_DEBUG |
  321.    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
  322.  
  323.   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
  324.   0,                /* leading char */
  325.   '/',                /* ar_pad_char */
  326.   15,                /* ar_max_namelen??? FIXMEmgo */
  327.   3,                /* default alignment power */
  328.  
  329.   _do_getb64, _do_getb_signed_64, _do_putb64,
  330.      _do_getb32, _do_getb_signed_32, _do_putb32,
  331.      _do_getb16, _do_getb_signed_16, _do_putb16, /* data */
  332.   _do_getb64, _do_getb_signed_64, _do_putb64,
  333.      _do_getb32, _do_getb_signed_32, _do_putb32,
  334.      _do_getb16, _do_getb_signed_16, _do_putb16, /* hdrs */
  335.  
  336.   {_bfd_dummy_target, coff_object_p,     /* bfd_check_format */
  337.      coff_archive_p,
  338. #ifdef    COREFILES_PLEASE
  339.      rs6000coff_core_p
  340. #else
  341.      _bfd_dummy_target
  342. #endif
  343.        },
  344.   {bfd_false, coff_mkobject, coff_mkarchive, /* bfd_set_format */
  345.      bfd_false},
  346.   {bfd_false, coff_write_object_contents,    /* bfd_write_contents */
  347.      _bfd_write_archive_contents, bfd_false},
  348.  
  349.   JUMP_TABLE(coff),
  350.   COFF_SWAP_TABLE,
  351. };
  352.